/*
 * Copyright (c) SiteWhere, LLC. All rights reserved. http://www.sitewhere.com
 *
 * The software in this package is published under the terms of the CPAL v1.0
 * license, a copy of which has been included with this distribution in the
 * LICENSE.txt file.
 */
package com.smartthing.hbase.tenant;

import org.apache.hadoop.hbase.regionserver.BloomType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.smartthing.hbase.HBaseContext;
import com.smartthing.hbase.ISmartThingHBase;
import com.smartthing.hbase.ISmartThingHBaseClient;
import com.smartthing.hbase.common.SmartThingTables;
import com.smartthing.hbase.encoder.IPayloadMarshaler;
import com.smartthing.hbase.encoder.JsonPayloadMarshaler;
import com.smartthing.hbase.user.UserIdManager;
import com.smartthing.server.lifecycle.LifecycleComponent;
import com.smartthing.spi.SmartThingException;
import com.smartthing.spi.search.ISearchResults;
import com.smartthing.spi.search.user.ITenantSearchCriteria;
import com.smartthing.spi.server.lifecycle.ILifecycleProgressMonitor;
import com.smartthing.spi.server.lifecycle.LifecycleComponentType;
import com.smartthing.spi.tenant.ITenant;
import com.smartthing.spi.tenant.ITenantManagement;
import com.smartthing.spi.tenant.request.ITenantCreateRequest;

/**
 * HBase implementation of SiteWhere tenant management.
 * 
 * @author Derek
 */
public class HBaseTenantManagement extends LifecycleComponent implements ITenantManagement {

    /** Static logger instance */
    private static final Logger LOGGER = LogManager.getLogger();

    /** Used to communicate with HBase */
    private ISmartThingHBaseClient client;

    /** Injected payload encoder */
    private IPayloadMarshaler payloadMarshaler = new JsonPayloadMarshaler();

    /** Supplies context to implementation methods */
    private HBaseContext context;

    /** User id manager */
    private UserIdManager userIdManager;

    public HBaseTenantManagement() {
	super(LifecycleComponentType.DataStore);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.smartthing.server.lifecycle.LifecycleComponent#start(com.smartthing.spi
     * .server.lifecycle.ILifecycleProgressMonitor)
     */
    @Override
    public void start(ILifecycleProgressMonitor monitor) throws SmartThingException {
	ensureTablesExist();

	// Create context from configured options.
	this.context = new HBaseContext();
	context.setClient(getClient());
	context.setPayloadMarshaler(getPayloadMarshaler());

	// Create device id manager instance.
	userIdManager = new UserIdManager();
	userIdManager.load(context);
	context.setUserIdManager(userIdManager);
    }

    /**
     * Ensure that the tables this implementation depends on are there.
     * 
     * @throws SmartThingException
     */
    protected void ensureTablesExist() throws SmartThingException {
	SmartThingTables.assureTable(client, ISmartThingHBase.USERS_TABLE_NAME, BloomType.ROW);
	SmartThingTables.assureTable(client, ISmartThingHBase.UID_TABLE_NAME, BloomType.ROW);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.smartthing.spi.server.lifecycle.ILifecycleComponent#getLogger()
     */
    @Override
    public Logger getLogger() {
	return LOGGER;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.smartthing.spi.tenant.ITenantManagement#createTenant(com.smartthing.spi
     * .tenant. request.ITenantCreateRequest)
     */
    @Override
    public ITenant createTenant(ITenantCreateRequest request) throws SmartThingException {
	return HBaseTenant.createTenant(context, request);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.smartthing.spi.tenant.ITenantManagement#updateTenant(java.lang.String,
     * com.smartthing.spi.tenant.request.ITenantCreateRequest)
     */
    @Override
    public ITenant updateTenant(String id, ITenantCreateRequest request) throws SmartThingException {
	return HBaseTenant.updateTenant(context, id, request);
    }

    /*
     * (non-Javadoc)
     * 
     * @see com.smartthing.spi.tenant.ITenantManagement#getTenantById(java.lang.
     * String)
     */
    @Override
    public ITenant getTenantById(String id) throws SmartThingException {
	return HBaseTenant.getTenantById(context, id);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.smartthing.spi.tenant.ITenantManagement#getTenantByAuthenticationToken
     * (java.lang .String)
     */
    @Override
    public ITenant getTenantByAuthenticationToken(String token) throws SmartThingException {
	return HBaseTenant.getTenantByAuthenticationToken(context, token);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.smartthing.spi.tenant.ITenantManagement#listTenants(com.smartthing.spi.
     * search. user.ITenantSearchCriteria)
     */
    @Override
    public ISearchResults<ITenant> listTenants(ITenantSearchCriteria criteria) throws SmartThingException {
	return HBaseTenant.listTenants(context, criteria);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * com.smartthing.spi.tenant.ITenantManagement#deleteTenant(java.lang.String,
     * boolean)
     */
    @Override
    public ITenant deleteTenant(String tenantId, boolean force) throws SmartThingException {
	return HBaseTenant.deleteTenant(context, tenantId, force);
    }

    public ISmartThingHBaseClient getClient() {
	return client;
    }

    public void setClient(ISmartThingHBaseClient client) {
	this.client = client;
    }

    public IPayloadMarshaler getPayloadMarshaler() {
	return payloadMarshaler;
    }

    public void setPayloadMarshaler(IPayloadMarshaler payloadMarshaler) {
	this.payloadMarshaler = payloadMarshaler;
    }
}